package com.starxg.m3u8.gui;

import java.util.concurrent.Future;
import java.util.function.Consumer;

import com.starxg.m3u8.utils.ThreadPoolUtils;

import javafx.application.Platform;

/**
 * IPromise
 * 
 * @author huangxingguang@lvmama.com
 * @date 2020-08-13 17:47
 */
public class Promise<T> implements IPromise<T> {
    private Consumer<T> then;
    private Consumer<Throwable> error;
    private Runnable complete;
    private volatile boolean accept;
    private PromiseCallback<T> promiseCallback;
    private Future<?> future;

    public Promise(PromiseCallback<T> promiseCallback) {
        this.promiseCallback = promiseCallback;
    }

    @Override
    public IPromise<T> then(Consumer<T> t) {
        this.then = t;
        return this;
    }

    @Override
    public IPromise<T> error(Consumer<Throwable> t) {
        this.error = t;
        return this;
    }

    @Override
    public IPromise<T> complete(Runnable t) {
        this.complete = t;
        future = ThreadPoolUtils.submit(() -> {
            if (promiseCallback == null) {
                return;
            }

            try {
                promiseCallback.accept(resolve -> {
                    if (this.then != null && !accept) {
                        Platform.runLater(() -> this.then.accept(resolve));
                    }
                    accept = true;
                }, reject -> {
                    if (this.error != null && !accept) {
                        Platform.runLater(() -> this.error.accept(reject));
                    }
                    accept = true;
                });
            } catch (Exception e) {
                if (this.error != null && !accept) {
                    Platform.runLater(() -> this.error.accept(e));
                }
                accept = true;
            } finally {
                if (complete != null) {
                    Platform.runLater(complete);
                }
            }

        });
        return this;
    }

    @Override
    public IPromise<T> complete() {
        return complete(null);
    }

    @Override
    public void cancel() {
        future.cancel(true);
    }

}
